﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Nachos.Machine
{
    public class Instruction
    {
        /*
         * OpCode values.  The names are straight from the MIPS
         * manual except for the following special ones:
         *
         * OP_UNIMP -		means that this instruction is legal, but hasn't
         *			been implemented in the simulator yet.
         * OP_RES -		means that this is a reserved opcode (it isn't
         *			supported by the architecture).
         */

        public const int OP_ADD = 1;
        public const int OP_ADDI = 2;
        public const int OP_ADDIU = 3;
        public const int OP_ADDU = 4;
        public const int OP_AND = 5;
        public const int OP_ANDI = 6;
        public const int OP_BEQ = 7;
        public const int OP_BGEZ = 8;
        public const int OP_BGEZAL = 9;
        public const int OP_BGTZ = 10;
        public const int OP_BLEZ = 11;
        public const int OP_BLTZ = 12;
        public const int OP_BLTZAL = 13;
        public const int OP_BNE = 14;

        public const int OP_DIV = 16;
        public const int OP_DIVU = 17;
        public const int OP_J = 18;
        public const int OP_JAL = 19;
        public const int OP_JALR = 20;
        public const int OP_JR = 21;
        public const int OP_LB = 22;
        public const int OP_LBU = 23;
        public const int OP_LH = 24;
        public const int OP_LHU = 25;
        public const int OP_LUI = 26;
        public const int OP_LW = 27;
        public const int OP_LWL = 28;
        public const int OP_LWR = 29;

        public const int OP_MFHI = 31;
        public const int OP_MFLO = 32;

        public const int OP_MTHI = 34;
        public const int OP_MTLO = 35;
        public const int OP_MULT = 36;
        public const int OP_MULTU = 37;
        public const int OP_NOR = 38;
        public const int OP_OR = 39;
        public const int OP_ORI = 40;
        public const int OP_RFE = 41;
        public const int OP_SB = 42;
        public const int OP_SH = 43;
        public const int OP_SLL = 44;
        public const int OP_SLLV = 45;
        public const int OP_SLT = 46;
        public const int OP_SLTI = 47;
        public const int OP_SLTIU = 48;
        public const int OP_SLTU = 49;
        public const int OP_SRA = 50;
        public const int OP_SRAV = 51;
        public const int OP_SRL = 52;
        public const int OP_SRLV = 53;
        public const int OP_SUB = 54;
        public const int OP_SUBU = 55;
        public const int OP_SW = 56;
        public const int OP_SWL = 57;
        public const int OP_SWR = 58;
        public const int OP_XOR = 59;
        public const int OP_XORI = 60;
        public const int OP_SYSCALL = 61;
        public const int OP_UNIMP = 62;
        public const int OP_RES = 63;
        public const int MaxOpcode = 63;
        static OpInfo opTable[] = {
    {SPECIAL, RFMT}, {BCOND, IFMT}, {OP_J, JFMT}, {OP_JAL, JFMT},
    {OP_BEQ, IFMT}, {OP_BNE, IFMT}, {OP_BLEZ, IFMT}, {OP_BGTZ, IFMT},
    {OP_ADDI, IFMT}, {OP_ADDIU, IFMT}, {OP_SLTI, IFMT}, {OP_SLTIU, IFMT},
    {OP_ANDI, IFMT}, {OP_ORI, IFMT}, {OP_XORI, IFMT}, {OP_LUI, IFMT},
    {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT},
    {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT},
    {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT},
    {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT},
    {OP_LB, IFMT}, {OP_LH, IFMT}, {OP_LWL, IFMT}, {OP_LW, IFMT},
    {OP_LBU, IFMT}, {OP_LHU, IFMT}, {OP_LWR, IFMT}, {OP_RES, IFMT},
    {OP_SB, IFMT}, {OP_SH, IFMT}, {OP_SWL, IFMT}, {OP_SW, IFMT},
    {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_SWR, IFMT}, {OP_RES, IFMT},
    {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT},
    {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT},
    {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT}, {OP_UNIMP, IFMT},
    {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}
};
        /// <summary>
        /// binary representation of the instruction
        /// </summary>
        public uint BinaryValue { get; set; }
        /// <summary>
        /// Type of instruction.  This is NOT the same as the
        /// opcode field from the instruction: see defs in mips.h
        /// </summary>
        public byte opCode { get; set; }
        /// <summary>
        /// // Three registers from instruction.
        /// Immediate or target or shamt field or offset.
        // Immediates are sign-extended.
        /// </summary>
        public byte RS { get; set; }
        public byte RT { get; set; }
        public byte RD { get; set; }
        public int Extra { get; set; }     
        /// <summary>
        /// decode the binary representation of the instruction
        /// </summary>
        void Decode()
        {
        }
    }
}
